﻿#if UNITY_EDITOR

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace AI.Graph.Editor {


    public class StatisticsPanel {

#region Static

        private const string clearUnityHistoryTitle = "Clear Unity History";
        private const string clearUnityHistoryMessage = "Do you want to delete the Unity history?\nYou cannot undo this action.";

#endregion


#region Fields

        private AIGraph m_graph;
        private Action m_repaintCallback;
        private Vector2 m_scrollPosition;
        private bool m_isVerticalScrollbarEnabled;

        private int m_averageUPS;
        private Queue<int> m_averageUPSQueue = new Queue<int> ();
        private double m_lastUPSUpdateTime;
        private int m_fps;
        private int m_fpsCounter;
        private double m_lastFpsReset;

#endregion


        public StatisticsPanel (AIGraph graph, Action repaintCallback) {
            m_graph = graph;
            m_repaintCallback = repaintCallback;

            GraphUndo.onRecordsChanged -= Repaint;
            GraphUndo.onRecordsChanged += Repaint;
        }


        void Repaint () {
            m_repaintCallback.Invoke ();
        }


        public void OnGUI (Rect rect) {
            CalculateFPS ();


            float windowBorder = 2;
            EditorGUI.DrawSolidTexture (rect, EditorGUI.toolbarOutlineColor.color, new BorderWidth (windowBorder));

            Rect windowRect = new Rect (rect.x + windowBorder, rect.y + windowBorder, rect.width - windowBorder * 2, rect.height - windowBorder * 2);
            GUILayout.BeginArea (windowRect);
            DrawWindow (windowRect.width, windowRect.height);
            GUILayout.EndArea ();

            Repaint ();
        }


        void CalculateFPS () {
            // count draw events per second.
            if (Event.current.type == EventType.Repaint) {
                m_fpsCounter++;
                if (EditorApplication.timeSinceStartup >= m_lastFpsReset + 1) {
                    m_fps = m_fpsCounter;
                    m_fpsCounter = 0;
                    m_lastFpsReset = EditorApplication.timeSinceStartup;
                }
            }

            // we want only an average of 30 entry's. 
            if (m_averageUPSQueue.Count == 30) {
                m_averageUPSQueue.Dequeue ();
            }

            // calculate updates per seconds.
            m_averageUPSQueue.Enqueue ((int) (1 / m_graph.deltaTime));

            // calculate the average updates per seconds.
            if (EditorApplication.timeSinceStartup > m_lastUPSUpdateTime + 1) {
                int sum = 0;
                int i = 0;
                foreach (int f in m_averageUPSQueue) {
                    sum += f;
                    i++;
                }

                m_averageUPS = sum / i;
                m_lastUPSUpdateTime = EditorApplication.timeSinceStartup;
            }
        }


        void DrawToolbarGUI (float width) {
            Rect rect = new Rect (0, 0, width, Styles.toolbarHeight);
            EditorGUI.Toolbar (rect, false, false, false, true);
            EditorGUI.Label (new Rect(rect.x, rect.y - 1, rect.width, rect.height), "Statistics", EditorGUI.textStyleCenter);
        }


        void DrawWindow (float width, float height) {
            DrawToolbarGUI (width);

            GUILayout.BeginArea (new Rect (0, Styles.toolbarHeight, width, height - Styles.toolbarHeight));

            DrawStatistics (new Rect (0, 0, width, height - Styles.toolbarHeight));

            GUILayout.EndArea ();
        }


        void DrawStatistics (Rect rect) {
            EditorGUI.DrawSolidTexture (rect, Styles.backgroundColor.color);

            EditorGUILayout.BeginVertical ();

            GUILayout.Space (7);

            EditorGUILayout.BeginHorizontal ();

            GUILayout.Space (7);

            EditorGUILayout.BeginVertical ();

            float nameWidth = 80;

            EditorGUILayout.BeginHorizontal ();
            EditorGUILayout.LabelField ("FPS:", EditorGUI.textStyleLeft, GUILayout.Width (nameWidth));
            EditorGUILayout.LabelField (m_fps.ToString (), EditorGUI.textStyleLeft);
            EditorGUILayout.EndHorizontal ();

            GUILayout.Space (5);

            EditorGUILayout.BeginHorizontal ();
            EditorGUILayout.LabelField ("UPS:", EditorGUI.textStyleLeft, GUILayout.Width (nameWidth));
            EditorGUILayout.LabelField (m_averageUPS.ToString (), EditorGUI.textStyleLeft);
            EditorGUILayout.EndHorizontal ();

            GUILayout.Space (5);

            EditorGUILayout.BeginHorizontal ();
            EditorGUILayout.LabelField ("DeltaTime:", EditorGUI.textStyleLeft, GUILayout.Width (nameWidth));
            EditorGUILayout.LabelField ($"{m_graph.deltaTime:N5}", EditorGUI.textStyleLeft);
            EditorGUILayout.EndHorizontal ();

            EditorGUILayout.EndVertical ();

            EditorGUILayout.EndHorizontal ();

            EditorGUILayout.EndVertical ();
        }


        static class Styles {

            public static readonly EditorColor backgroundColor = new EditorColor(new Color32 (230, 230, 230, 120), new Color32 (56, 56, 56, 120));
            public static readonly float toolbarHeight = 18;

        }

    }


}
#endif